﻿using System;
using System.Collections;
using System.Collections.Generic;
using Petra.Gis.Geometry;
using Petra.Gis.DataServices;
using Petra.Gis.DataServices.Metadata;
using Petra.Gis.ReferenceSystemServices.Transformations;

namespace Petra.Gis.RenderingServices.PlanarBase 
{
  /// <summary>
  /// represents legend node that can holds spatial data to display in map
  /// this node supports any <c>IEnumerable</c> data type with valid 
  /// <c>SpatialMetadata</c> supplied as param
  /// if enumerable type doesnt contain geometries directly <c>IConverted</c>
  /// might be specified to extract geometry data from
  /// </summary>
  public class ObjectLegendNode : LegendNode
  {

    protected IConverter _converter;
    protected IEnumerable _data;
    protected SpatialMetadata _metadata;




    public ObjectLegendNode(LegendNode parent, IEnumerable data, SpatialMetadata metadata, string title)
      : base(parent, title)
    {
      _nodeType = LegendNodeType.DataNode;
      _data = data;
      
    }




    public ObjectLegendNode(LegendNode parent, IEnumerable data, SpatialMetadata metadata, IConverter converter, string title)
      : base(parent, title)
    {
      _nodeType = LegendNodeType.DataNode;
      _data = data;
      _converter = converter;
      _metadata = metadata;
    }




    public override void RenderData()
    {

      //prepare styles for draw..


      // prepare SRSTransforms
      // put each spatial filed transform into new array item to search then
      Dictionary<string, SRSTransform> spatialFields = new Dictionary<string, SRSTransform>();
      foreach (GeometryFieldMetadata gfm in _metadata.GeometryFieldsMetadata)
      {
        //get appropriate (non reverse) transform for each spatial field
        spatialFields.Add(gfm.Name, this.Legend.Map.SRSTransformCache.GetTransform(gfm.SRS, false));
      }

      // load data
      // step over records and paint into map...
      GeometryBase g;

      foreach (object obj in _data)
      {
        foreach (KeyValuePair<string, SRSTransform> sft in spatialFields)
        {
          if (_converter != null)
            g = _converter.getGeometry(obj, sft.Key);
          else
            g = (GeometryBase)obj;

          //todo:apply spatial filter here ?
          //since IEnumerable is memory object, can always apply spatial filter

          foreach (Renderer r in Renderers)
          {
            if (g is Grid)
            {
              ((Grid)g).Transform = sft.Value;
              //((Grid)g).InverseTransform = this.Legend.Map.SRSTransformCache.GetTransform(sft.Value.Source, true);

              if (sft.Value.IsInversible)
                ((Grid)g).InverseTransform = sft.Value.Inverse();
              else
                ((Grid)g).InverseTransform = this.Legend.Map.SRSTransformCache.GetTransform(sft.Value.Source, true);

              r.RenderGeometry((Grid)g);

            }
            else
              r.RenderGeometry( sft.Value.Transform(g) );
          }
        }
      }


    }




    public IEnumerable Data
    {
      get { return _data; }
    }



  }
}
